function Gears(appUpdateCallBack) {
  this._factory = null;
  this._localServer = null;
  this._mstore = null;
  this._db = null;
  this._desktop = null;
  this._handleAppUpdate = appUpdateCallBack;
  this.hasGears = false;
  this._registerStoreEvent = false;

  if (window.google && google.gears) {
    this.hasGears = true;
    this._factory = google.gears.factory;
    try {
      if (!this.hasPermission())
        this._factory.getPermission();
      if (this.hasPermission()) {
        this._localServer = this._factory.create('beta.localserver');
        this._db = this._factory.create('beta.database');
        this._desktop = this._factory.create('beta.desktop');
        this._initialManagedStore();
      }
    } catch(e) {logging('initial gears exception: '+e);}
  }
}

Gears.prototype._initialManagedStore = function() {
  try {
    if (this._mstore) {
      this._mstore = this._localServer.openManagedStore('ezkeypad');
    } else {
      this._mstore = this._localServer.createManagedStore('ezkeypad');
    }
  } catch(e) {logging('initial managed store exception: '+e)}
  var self = this;
  if (!this._registerStoreEvent) {
    this._mstore.oncomplete = function(o) {
      //logging('managed store oncomplete');
      if (o.newVersion) 
        self._handleAppUpdate(o.newVersion); 
    };
    this._mstore.onerror = function(e) {
      logging('managed store onerror'+e.message);
      self._handleAppUpdate(null);
    };
    this._registerStoreEvent = true;
  }
}

// enable offline feature
Gears.prototype.capture = function() { // param is callback function 
  if (this.isCaptured()) {
    this._handleAppUpdate(this._mstore.currentVersion);
    return;
  }
  this._initialManagedStore();
  this._mstore.manifestUrl = '/ezkeypad/ez_menifest';
  this._mstore.checkForUpdate();
};

// disable offline feature
Gears.prototype.uncapture = function() {
  if (this.isCaptured()) {
    try {
      this._localServer.removeManagedStore('ezkeypad');
      this._mstore = null;
      this._registerStoreEvent = false;
    } catch(e) {logging('uncapture exception: '+e);}
  }
};

Gears.prototype.isCaptured = function() {
  return Boolean(this._mstore && this._mstore.currentVersion);
};

Gears.prototype.getCurrentVersion = function() {
  return this.isCaptured() ? this._mstore.currentVersion : null;
};

Gears.prototype.createDesktopShortcut = function() {
  icons = {
    '128x128': '/ezkeypad/media/icon128.png',
    '48x48': '/ezkeypad/media/icon48.png',
    '32x32': '/ezkeypad/media/icon32.png',
    '16x16': '/ezkeypad/media/icon16.png'
  };
  name = 'ezKeypad - A.TNG Labs Innovations';
  description = '';
  this._desktop.createShortcut(name, 
    '/', 
    icons, 
    description);
};

Gears.prototype.hasPermission = function() {
  return Boolean(this.hasGears && this._factory.hasPermission);
};